﻿using System;
using System.Collections;
using System.Text;

namespace MyFastDataSourceBind
{
    /// <summary>
    /// 数据源事件广播器
    /// </summary>
    /// <remarks>编写 袁永福</remarks>
    public class XDataSourceEventSender
    {
/// <summary>
/// 注册数据绑定对象
/// </summary>
/// <param name="obj">数据绑定对象</param>
/// <param name="DataSource">绑定的数据源的名称</param>
public static void Register(IXDataSourceable obj, string DataSource)
{
    if (obj == null)
    {
        throw new ArgumentNullException("obj");
    }
    // 获得信息项目
    DataSourceEvnetItem item = GetItem(obj);
    // 从数据源全局列表中获得指定名称的数据源对象
    XDataSource ds = XDataSource.GetInstance(DataSource);
    if (ds == null)
    {
        // 若没有找到指定名称的数据源对象则删除错误的信息，抛出异常
        if (item != null)
        {
            myItems.Remove(item);
        }
        System.Console.WriteLine("Bad DataSource:" + DataSource);
        return;
    }
    if (item == null)
    {
        // 创建新的注册信息
        item = new DataSourceEvnetItem();
        item.Object = obj;
        myItems.Add(item);
    }
    // 设置注册信息中的数据源对象
    item.DataSource = ds;
}

/// <summary>
/// 取消注册数据源绑定对象
/// </summary>
/// <param name="obj">取消的对象</param>
public static void UnRegister(IXDataSourceable obj)
{
    // 检查参数
    if (obj == null)
    {
        throw new ArgumentNullException("obj");
    }
    // 获得注册信息
    DataSourceEvnetItem item = GetItem(obj);
    if (item != null)
    {
        // 删除注册信息
        myItems.Remove(item);
    }
}

/// <summary>
/// 删除所有指定数据源相关的绑定信息
/// </summary>
/// <param name="datasource">数据源对象</param>
public static void RemoveDataSource(XDataSource datasource)
{
    for (int iCount = myItems.Count - 1; iCount >= 0; iCount--)
    {
        DataSourceEvnetItem item = (DataSourceEvnetItem)myItems[iCount];
        if (item.DataSource == datasource)
        {
            // 删除注册信息
            myItems.RemoveAt(iCount);
        }
    }
}

/// <summary>
/// 广播数据源事件
/// </summary>
/// <param name="datasource">数据源对象</param>
/// <param name="style">事件类型</param>
/// <returns>操作是否成功</returns>
public static bool RaiseEvent(XDataSource datasource, XDataSourceEventStyle style)
{
    // 创建事件参数
    XDataSourceEventArgs args = new XDataSourceEventArgs(style, datasource);
    for (int iCount = myItems.Count - 1; iCount >= 0; iCount--)
    {
        // 由于在循环中可能要删除注册信息，因此需要反向遍历
        DataSourceEvnetItem item = (DataSourceEvnetItem)myItems[iCount];
        if (item.DataSource == datasource && item.Object != null)
        {
            // 找到匹配的注册信息
            if (item.Object is System.Windows.Forms.Control)
            {
                // 若对象是WinForm控件则检查控件状态
                System.Windows.Forms.Control ctl = (System.Windows.Forms.Control)item.Object;
                if (ctl.IsDisposed)
                {
                    // 若WinForm控件已经销毁掉了则删除该控件的绑定信息
                    myItems.RemoveAt(iCount);
                    continue;
                }
            }
            // 调用对象的HandleDataSourceEvent方法，驱动用户界面层处理数据源事件。
            item.Object.HandleDataSourceEvent(datasource, args);
            if (args.Cancel)
            {
                // 若用户取消了操作则立即退出事件处理
                return false;
            }
        }
    }
    // 成功的广播了数据源事件，返回true
    return true;
}

private static ArrayList myItems = new ArrayList();
/// <summary>
/// 获得指定数据需求对象的数据源事件绑定信息对象
/// </summary>
/// <param name="obj">数据需求对象</param>
/// <returns>数据源事件绑定信息</returns>
private static DataSourceEvnetItem GetItem(IXDataSourceable obj)
{
    foreach (DataSourceEvnetItem item in myItems)
    {
        if (item.Object == obj)
        {
            return item;
        }
    }
    return null;
}

/// <summary>
/// 数据源事件绑定信息对象
/// </summary>
private class DataSourceEvnetItem
{
    /// <summary>
    /// 数据源对象
    /// </summary>
    public XDataSource DataSource = null;
    /// <summary>
    /// 数据源绑定对象
    /// </summary>
    public IXDataSourceable Object = null;
}
    }//public class XDataSourceEventSender
}